package com.qingyouchuxing.mall.biz.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import cn.hutool.core.util.ObjectUtil;
import com.mybatisflex.core.keygen.IKeyGenerator;
import com.mybatisflex.core.keygen.KeyGeneratorFactory;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.qingyouchuxing.mall.biz.convert.MallGoodsSkuConvert;
import com.qingyouchuxing.mall.biz.convert.MallGoodsSpuConvert;
import com.qingyouchuxing.mall.biz.domain.bo.MallGoodsBO;
import com.qingyouchuxing.mall.biz.domain.bo.MallGoodsSkuBO;
import com.qingyouchuxing.mall.biz.domain.bo.MallGoodsSpuBO;
import com.qingyouchuxing.mall.biz.domain.dto.MallGoodsDTO;
import com.qingyouchuxing.mall.biz.domain.dto.MallGoodsFromDTO;
import com.qingyouchuxing.mall.biz.domain.dto.MallGoodsStatusDTO;
import com.qingyouchuxing.mall.biz.domain.entity.MallGoods;
import com.qingyouchuxing.mall.biz.domain.entity.MallGoodsClassify;
import com.qingyouchuxing.mall.biz.domain.entity.MallGoodsSku;
import com.qingyouchuxing.mall.biz.domain.entity.MallGoodsSpu;
import com.qingyouchuxing.mall.biz.domain.vo.MallGoodsVO;
import com.qingyouchuxing.mall.biz.mapper.MallGoodsClassifyMapper;
import com.qingyouchuxing.mall.biz.mapper.MallGoodsMapper;
import com.qingyouchuxing.mall.biz.mapper.MallGoodsSkuMapper;
import com.qingyouchuxing.mall.biz.mapper.MallGoodsSpuMapper;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.BigDecimalUtils;
import com.ruoyi.common.core.utils.CollectionUtils;
import com.ruoyi.common.core.utils.MapstructUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.orm.core.page.TableDataInfo;
import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.qingyouchuxing.mall.biz.service.IMallGoodsService;

import static com.qingyouchuxing.mall.biz.domain.entity.table.MallGoodsTableDef.MALL_GOODS;


/**
 * 商品Service业务层处理
 *
 * @author 数据小王子
 * 2024-09-06
 */
@Service
public class MallGoodsServiceImpl extends BaseServiceImpl<MallGoodsMapper, MallGoods> implements IMallGoodsService {
    @Autowired
    private MallGoodsMapper mallGoodsMapper;
    @Autowired
    private MallGoodsClassifyMapper mallGoodsClassifyMapper;
    @Autowired
    private MallGoodsSpuMapper mallGoodsSpuMapper;
    @Autowired
    private MallGoodsSkuMapper mallGoodsSkuMapper;

    @Override
    public QueryWrapper query() {
        return super.query().from(MALL_GOODS);
    }

    private QueryWrapper buildQueryWrapper(MallGoodsBO mallGoodsBO) {
        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
        queryWrapper.and(MALL_GOODS.ID.eq(mallGoodsBO.getId()));
        queryWrapper.and(MALL_GOODS.GOODS_NAME.like(mallGoodsBO.getGoodsName()));
        queryWrapper.and(MALL_GOODS.PRICE.eq(mallGoodsBO.getPrice()));
        queryWrapper.and(MALL_GOODS.SALE_PRICE.eq(mallGoodsBO.getSalePrice()));
        queryWrapper.and(MALL_GOODS.COST_PRICE.eq(mallGoodsBO.getCostPrice()));
        queryWrapper.and(MALL_GOODS.IMAGE.eq(mallGoodsBO.getImage()));
        queryWrapper.and(MALL_GOODS.INFO_IMAGE.eq(mallGoodsBO.getInfoImage()));
        queryWrapper.and(MALL_GOODS.FREIGHT_PRICE.eq(mallGoodsBO.getFreightPrice()));

        return queryWrapper;
    }

    @Transactional
    @Override
    public boolean updateStatus(MallGoodsStatusDTO dto) {
        MallGoods mallGoods = getByIdOpt(dto.getId()).orElseThrow(() -> new ServiceException("不存在的商品"));
        mallGoods.setStatus(dto.getStatus());
        return updateById(mallGoods);
    }

    /**
     * 查询商品
     *
     * @param id 商品主键
     * @return 商品
     */
    @Override
    public MallGoodsVO selectById(Long id) {
        MallGoodsVO info = mallGoodsMapper.info(id);
        List<MallGoodsSpu> mallGoodsSpuList = mallGoodsSpuMapper.selectListByFkGoodsId(info.getId());
        List<Long> spuIds = mallGoodsSpuList.stream().map(MallGoodsSpu::getId).collect(Collectors.toList());
        List<MallGoodsSku> mallGoodsSkus = mallGoodsSkuMapper.selectListByFkSpuId(spuIds);
        Map<Long, List<MallGoodsSku>> mallGoodsSkusGroup = CollectionUtils.group(mallGoodsSkus, MallGoodsSku::getFkSpuId);
        List<MallGoodsSpuBO> spuList = mallGoodsSpuList.stream().map(item -> {
            MallGoodsSpuBO mallGoodsSpuBO = MallGoodsSpuConvert.INSTANCES.entityToBO(item);
            List<MallGoodsSku> skuList = mallGoodsSkusGroup.get(item.getId());
            mallGoodsSpuBO.setSkuList(MallGoodsSkuConvert.INSTANCES.entityToBO(skuList));
            return mallGoodsSpuBO;
        }).collect(Collectors.toList());
        info.setSpuList(spuList);
        return info;
//        return this.getOneAs(query().where(MALL_GOODS.ID.eq(id)), MallGoodsVO.class);

    }

    /**
     * 查询商品列表
     *
     * @param mallGoodsBO 商品Bo
     * @return 商品集合
     */
    @Override
    public List<MallGoodsVO> selectList(MallGoodsBO mallGoodsBO) {
        QueryWrapper queryWrapper = buildQueryWrapper(mallGoodsBO);
        return this.listAs(queryWrapper, MallGoodsVO.class);
    }

    /**
     * 分页查询商品列表
     *
     * @param dto 商品DTO
     * @return 分页商品集合
     */
    @Override
    public TableDataInfo<MallGoodsVO> selectPage(MallGoodsDTO dto) {
        Page<MallGoodsVO> page = mapper.selectPage(dto);
        return TableDataInfo.build(page);
    }

    /**
     * 新增商品
     *
     * @param dto 商品dto
     * @return 结果:true 操作成功，false 操作失败
     */
    @Transactional
    @Override
    public boolean insert(MallGoodsFromDTO dto) {
        Long fkClassifyId = dto.getFkClassifyId();
        MallGoodsClassify mallGoodsClassify = mallGoodsClassifyMapper.selectOneById(fkClassifyId);
        if (ObjectUtil.isNull(mallGoodsClassify)) {
            throw new ServiceException("分类不存在,请重新选择分类");
        }
        MallGoods mallGoods = MapstructUtils.convert(dto, MallGoods.class);
        String image = StringUtils.join(dto.getImageList(), ",");
        mallGoods.setImage(image);
        if (CollectionUtils.isNotEmpty(dto.getInfoImageList())) {
            String infoImage = StringUtils.join(dto.getInfoImageList(), ",");
            mallGoods.setInfoImage(infoImage);
        }
        // 保存商品信息
        boolean save = this.save(mallGoods);
        if (save) {
            List<MallGoodsSpuBO> spuList = dto.getSpuList();
            // 保存spu信息
            if (CollectionUtils.isNotEmpty(spuList)) {
                IKeyGenerator keyGenerator = KeyGeneratorFactory.getKeyGenerator("snowFlakeId");
                List<MallGoodsSku> mallGoodsSkuList = new ArrayList<>();
                spuList.forEach(item -> {
                    Long id = (Long) keyGenerator.generate(null, null);
                    item.setSpuId(id);
                    item.setFkGoodsId(mallGoods.getId());
                    item.getSkuList().forEach(sku -> {
                        if (BigDecimalUtils.gt(sku.getPriceFactor(), dto.getPrice())) {
                            throw new ServiceException("sku价格因子不能大于商品本身的价格");
                        }
                        sku.setFkSpuId(id);
                    });
                    if (CollectionUtils.isNotEmpty(item.getSkuList())) {
                        List<MallGoodsSku> mallGoodsSkus = MallGoodsSkuConvert.INSTANCES.boToEntity(item.getSkuList());
                        mallGoodsSkuList.addAll(mallGoodsSkus);
                    }
                });
                List<MallGoodsSpu> mallGoodsSpuList = MallGoodsSpuConvert.INSTANCES.boToEntity(spuList);
                save = mallGoodsSpuMapper.insertBatch(mallGoodsSpuList) > 0;
                if (save) {
                    // 保存sku信息
                    if (CollectionUtils.isNotEmpty(mallGoodsSkuList)) {
                        save = mallGoodsSkuMapper.insertBatch(mallGoodsSkuList) > 0;
                    }
                }
            }
        }
        return save;//使用全局配置的雪花算法主键生成器生成ID值
    }

    /**
     * 修改商品
     *
     * @param dto 商品dto
     * @return 结果:true 更新成功，false 更新失败
     */
    @Transactional
    @Override
    public boolean update(MallGoodsFromDTO dto) {
        Long fkClassifyId = dto.getFkClassifyId();
        MallGoodsClassify mallGoodsClassify = mallGoodsClassifyMapper.selectOneById(fkClassifyId);
        if (ObjectUtil.isNull(mallGoodsClassify)) {
            throw new ServiceException("分类不存在,请重新选择分类");
        }
        MallGoods mallGoods = MapstructUtils.convert(dto, MallGoods.class);
        String image = StringUtils.join(dto.getImageList(), ",");
        mallGoods.setImage(image);
        if (CollectionUtils.isNotEmpty(dto.getInfoImageList())) {
            String infoImage = StringUtils.join(dto.getInfoImageList(), ",");
            mallGoods.setInfoImage(infoImage);
        }
        // 保存商品信息
        this.updateById(mallGoods);
        List<MallGoodsSpuBO> spuList = dto.getSpuList();
        // 保存spu信息
        if (CollectionUtils.isNotEmpty(spuList)) {
            // id生成器
            IKeyGenerator keyGenerator = KeyGeneratorFactory.getKeyGenerator("snowFlakeId");
            List<MallGoodsSpu> mallGoodsSpuList = mallGoodsSpuMapper.selectListByFkGoodsId(dto.getId());
            List<Long> mallGoodsSpuIdList = mallGoodsSpuList.stream().map(MallGoodsSpu::getId).toList();
            List<Long> dtoMallGoodsSpuIdList = dto.getSpuList().stream().map(MallGoodsSpuBO::getSpuId).toList();
            Map<Long, MallGoodsSpuBO> dtoMallGoodsSpuIdMap = CollectionUtils.toMap(dto.getSpuList(), MallGoodsSpuBO::getSpuId, item -> item);
            // 获取交集,即获取需要修改的spu
            List<Long> spuIdUpdateList = mallGoodsSpuIdList.stream().filter(dtoMallGoodsSpuIdList::contains).toList();
            List<MallGoodsSku> mallGoodsSkuList = new ArrayList<>();
            spuIdUpdateList.forEach(spuId -> {
                MallGoodsSpuBO mallGoodsSpuBO = dtoMallGoodsSpuIdMap.get(spuId);
                MallGoodsSpu mallGoodsSpu = MallGoodsSpuConvert.INSTANCES.boToEntity(mallGoodsSpuBO);
                mallGoodsSpu.setFkGoodsId(dto.getId());
                // 编辑spu
                mallGoodsSpuMapper.update(mallGoodsSpu);
                // 转为map
                List<MallGoodsSku> mallGoodsSkus = mallGoodsSkuMapper.selectListByFkSpuId(spuId);
                Map<Long, MallGoodsSkuBO> mallGoodsSkuMap = CollectionUtils.toMap(mallGoodsSpuBO.getSkuList(), MallGoodsSkuBO::getSkuId, item -> item);
                List<Long> mallGoodsSkuIdList = mallGoodsSkus.stream().map(MallGoodsSku::getId).toList();
                List<Long> dtoMallGoodsSkuIdList = mallGoodsSpuBO.getSkuList().stream().map(MallGoodsSkuBO::getSkuId).toList();
                // 获取交集,即获取需要修改的sku
                List<Long> skuIdUpdateList = mallGoodsSkuIdList.stream().filter(dtoMallGoodsSkuIdList::contains).toList();
                skuIdUpdateList.forEach(skuId -> {
                    MallGoodsSkuBO mallGoodsSku = mallGoodsSkuMap.get(skuId);
                    if (BigDecimalUtils.gt(mallGoodsSku.getPriceFactor(), dto.getPrice())) {
                        throw new ServiceException("sku价格因子不能大于商品本身的价格");
                    }
                    // 编辑sku
                    mallGoodsSkuMapper.update(MallGoodsSkuConvert.INSTANCES.boToEntity(mallGoodsSku));
                });
                // skuId为空就是需要新增的sku
                // 获取需要新增的sku
                List<MallGoodsSkuBO> goodsSkuList = mallGoodsSpuBO.getSkuList().stream().filter(item -> ObjectUtil.isNull(item.getSkuId())).map(item -> {
                    item.setFkSpuId(spuId);
                    return item;
                }).collect(Collectors.toList());
                mallGoodsSkuList.addAll(MallGoodsSkuConvert.INSTANCES.boToEntity(goodsSkuList));
            });
            // 获取需要新增的spu
            List<MallGoodsSpu> spuIdInsertList = dto.getSpuList().stream().filter(item -> ObjectUtil.isNull(item.getSpuId())).map(spu -> {
                Long id = (Long) keyGenerator.generate(null, null);
                spu.setFkGoodsId(dto.getId());
                spu.setSpuId(id);
                mallGoodsSkuList.addAll(spu.getSkuList().stream().map(sku -> {
                    if (BigDecimalUtils.gt(sku.getPriceFactor(), dto.getPrice())) {
                        throw new ServiceException("sku价格因子不能大于商品本身的价格");
                    }
                    sku.setFkSpuId(id);
                    return MallGoodsSkuConvert.INSTANCES.boToEntity(sku);
                }).collect(Collectors.toList()));
                return MallGoodsSpuConvert.INSTANCES.boToEntity(spu);
            }).toList();
            if (CollectionUtils.isNotEmpty(spuIdInsertList)) {
                mallGoodsSpuMapper.insertBatch(spuIdInsertList);
            }
            if (CollectionUtils.isNotEmpty(mallGoodsSkuList)) {
                mallGoodsSkuMapper.insertBatch(mallGoodsSkuList);
            }
            if (CollectionUtils.isNotEmpty(dto.getDeleteSpuIds())) {
                mallGoodsSpuMapper.deleteBatchByIds(dto.getDeleteSpuIds());
            }
            if (CollectionUtils.isNotEmpty(dto.getDeleteSkuIds())) {
                mallGoodsSkuMapper.deleteBatchByIds(dto.getDeleteSkuIds());
            }
        }
        return true;//使用全局配置的雪花算法主键生成器生成ID值
    }

    /**
     * 批量删除商品
     *
     * @param ids 需要删除的商品主键集合
     * @return 结果:true 删除成功，false 删除失败
     */
    @Transactional
    @Override
    public boolean deleteByIds(Long[] ids) {
        return this.removeByIds(Arrays.asList(ids));
    }

}
